﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Kernel32.cs" company="Matthias Friedrich">
//   Copyright © Matthias Friedrich 2009
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace DeviceManagement
{
	using System;
	using System.Globalization;
	using System.Runtime.InteropServices;

	internal static class Kernel32
	{
		internal const long ERROR_SUCCESS = 0;

		private const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;

		private const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100;

		public static string GetLastErrorMessage()
		{
			uint err = GetLastError();

			IntPtr pBuffer;
			var languageId = (uint)CultureInfo.CurrentUICulture.LCID;
			if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, IntPtr.Zero, err, languageId, out pBuffer, 0, IntPtr.Zero) != 0)
			{
				return Marshal.PtrToStringAuto(pBuffer);
			}

			return "Unknown error.";
		}

		public static void ThrowDeviceManagementExceptionFromLastError()
		{
			uint e = GetLastError();
			string errorMessage = GetLastErrorMessage();
			if (e != ERROR_SUCCESS)
			{
				throw new DeviceManagementException(errorMessage);
			}
		}

		[DllImport("kernel32.dll", EntryPoint = "FormatMessage", CharSet = CharSet.Auto)]
		internal static extern uint FormatMessage(uint dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, out IntPtr lpBuffer, uint nSize, IntPtr arguments);

		[DllImport("kernel32.dll", EntryPoint = "FreeLibrary", CharSet = CharSet.Auto)]
		internal static extern bool FreeLibrary(IntPtr hModule);

		[DllImport("kernel32.dll", EntryPoint = "GetLastError")]
		internal static extern uint GetLastError();

		[DllImport("kernel32.dll", EntryPoint = "GetModuleHandle", CharSet = CharSet.Auto)]
		internal static extern IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPTStr)] string moduleName);

		[DllImport("kernel32.dll", EntryPoint = "GetProcAddress", CharSet = CharSet.Auto)]
		internal static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

		[DllImport("kernel32.dll", EntryPoint = "LoadLibrary", CharSet = CharSet.Auto)]
		internal static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPTStr)] string lpFileName);
	}
}